// Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.

// fleet服务端会话数据表定义
package dao

import (
	"fleetmanager/db/dbm"
	"fleetmanager/logger"
	"fmt"
	"sync"
	"time"
)

const (
	FieldNameServerSessionId = "server_session_id"
	FieldNameFleetId		 = "fleet_id"
	FieldNameCreationTime	 = "creation_time"
	FieldNameId	 			 = "id"
)

const (
	FleetServerSessionBackupCountToSleep = 50
	FleetServerSessionBackupCountToSleepSeconds = 1
)


// FleetServerSession TODO:fleetId作为外键关联fleet表
type FleetServerSession struct {
	Id              string    `orm:"column(id);size(128);pk"`
	FleetId         string    `orm:"column(fleet_id);size(128)"`
	ServerSessionId string    `orm:"column(server_session_id);size(128)"`
	Region          string    `orm:"column(region);size(64)" json:"region"`
	CreationTime    time.Time `orm:"column(creation_time);type(datetime);auto_now_add" json:"creation_time"`
}

func (s *FleetServerSession) TableIndex() [][]string {
	return [][]string{
		{FieldNameServerSessionId},
		{FieldNameCreationTime},
	}
}

type fleetSessionStorage struct{}

var fss = fleetSessionStorage{}

// GetFleetServerSessionStorage 获取Fleet服务器会话存储
func GetFleetServerSessionStorage() *fleetSessionStorage {
	return &fss
}

// Insert 插入Fleet服务器会话信息
func (s *fleetSessionStorage) Insert(fleetSession *FleetServerSession) error {
	_, err := dbm.Ormer.Insert(fleetSession)
	return err
}

// Insert 插入Fleet服务器会话信息
func (s *fleetSessionStorage) Delete(fleetSession *FleetServerSession) error {
	_, err := dbm.Ormer.Delete(fleetSession)
	return err
}

// GetOne 获取Fleet服务器会话信息
func (s *fleetSessionStorage) GetOne(f Filters) (*FleetServerSession, error) {
	var fleetSession FleetServerSession
	err := f.Filter(FleetServerSessionTable).One(&fleetSession)
	return &fleetSession, err
}

func (s *fleetSessionStorage) CleanFleetServerSession(dayBefore int) {
	var fsss []FleetServerSession
	sqlStr := fmt.Sprintf("SELECT * FROM %s WHERE %s < DATE_SUB(NOW(), INTERVAL %d DAY)", 
		FleetServerSessionTable, FieldNameCreationTime, dayBefore)
	toBeCleanCount, err := dbm.Ormer.Raw(sqlStr).QueryRows(&fsss)
	if err != nil {
		logger.R.Error("[express data cleaner] query to be clean fleet server session from runtime table failed: %+v", err)
		return
	}
	logger.R.Info("[express data cleaner] find %v expressed fleet server session from runtime table", toBeCleanCount)
	wg := sync.WaitGroup{}
	wg.Add(int(toBeCleanCount))
	for idx, fss := range fsss {
		if idx % FleetServerSessionBackupCountToSleep == 0 {
			time.Sleep(FleetServerSessionBackupCountToSleepSeconds * time.Second)
		}
		go func(f_server_session FleetServerSession) {
			defer wg.Done()
			errD := s.Delete(&f_server_session)
			if errD != nil {
				logger.R.Error("[express data cleaner] delete fleet server session %s from runtime table failed: %+v", 
				f_server_session.ServerSessionId, errD)
				return
			}
			logger.R.Info("[express data cleaner] delete fleet server session %s from runtime table success", 
			f_server_session.ServerSessionId)
		}(fss)
	}
	wg.Wait()
}
